/**
 * 滑块触摸移动事件
 */
import { ComponentInternalInstance, ref } from 'vue'
import {
  uuid
} from '../../../utils'

type SlideWrapperRect = {
  left: number,
  top: number,
  width: number,
  height: number
}
type SlideRect = {
  width: number,
  height: number
}

export default function useTouchEvent(instance: ComponentInternalInstance) {

  const id: string = uuid()
  const slideContainerRectID: string = `tn-slide-verify_${id}`
  const slideRectID: string = `tn-slide-verify-s_${id}`
  let initCount: number = 0
  let slideWrapperRect: SlideWrapperRect = {
    left: 0,
    top: 0,
    width: 0,
    height: 0
  }
  let slideRect: SlideRect = {
    width: 0,
    height: 0
  }
  let touching: boolean = false
  let touchID: number = -1
  let startTouchPosition: {
    x: number,
    y: number
  } = {
    x: 0,
    y: 0
  }

  let distance = ref<{
    x: number,
    y: number
  }>({
    x: 0,
    y: 0
  })
  let isPass = ref<boolean>(false)


  // 初始化容器相关信息
  const initRectInfo = () => {
    _getSlideWrapperRectInfo()
    _getSlideRectInfo()
  }

  // 开始触摸事件
  const slideStartTouchEvent = (e: TouchEvent) => {
    if (isPass.value) return
    const touches = e.touches
    if (!touches || touches.length < 0) return
    const touch = touches[0]
    touching = true
    touchID = touch.identifier
    startTouchPosition.x = touch.pageX
    startTouchPosition.y = touch.pageY
  }

  // 触摸移动事件
  const slideTouchMoveEvent = (e: TouchEvent) => {
    const touches = e.changedTouches
    if (!touches || touches.length < 0 || !touching) return
    const touch = touches[0]
    if (touchID !== touch.identifier) return

    // 计算滑动距离
    const x: number = touch.pageX
    const y: number = touch.pageY
    distance.value.x = x - startTouchPosition.x
    distance.value.y = y - startTouchPosition.y

    if (distance.value.x < 0) distance.value.x = 0
    if (distance.value.x > (slideWrapperRect.width - slideRect.width - 5)) distance.value.x = slideWrapperRect.width - slideRect.width - 5

  }

  // 触摸结束事件
  const slideTouchEndEvent = (e: TouchEvent) => {
    const touches = e.changedTouches
    if (!touches || touches.length < 0 || !touching) return
    const touch = touches[0]
    if (touchID !== touch.identifier) return

    // 判断移动的距离是否到达了进度条的尾部
    if (!_checkSlideSweepEnd()) {
      distance.value.x = 0
    } else {
      isPass.value = true
    }

    touching = false
    touchID = -1
    startTouchPosition.x = 0
    startTouchPosition.y = 0
  }

  // 重置滑动状态
  const resetSlideStatus = () => {
    isPass.value = false
    distance.value = {
      x: 0,
      y: 0
    }
  }

  // 检查滑块是否滑倒最尾部
  const _checkSlideSweepEnd = () => {
    return distance.value.x >= slideWrapperRect.width - slideRect.width - 5
  }


  // 获取滑动条的容器信息
  const _getSlideWrapperRectInfo = () => {
    const query = uni.createSelectorQuery().in(instance)
    query
      .select(`#${slideContainerRectID}`)
      .boundingClientRect((res) => {
        if (!res) {
          if (initCount > 20) {
            return console.error('[tn-slide-verify]获取容器信息失败')
          }
          initCount++
          setTimeout(() => {
            _getSlideWrapperRectInfo()
          }, 50)
          return
        }

        initCount = 0
        res = res as UniApp.NodeInfo
        slideWrapperRect.width = res?.width || 0
        slideWrapperRect.height = res?.height || 0
        slideWrapperRect.top = res?.top || 0
        slideWrapperRect.left = res?.left || 0
      })
      .exec()
  }

  // 获取滑块的容器信息
  const _getSlideRectInfo = () => {
    const query = uni.createSelectorQuery().in(instance)
    query
      .select(`#${slideRectID}`)
      .boundingClientRect((res) => {
        if (!res) {
          if (initCount > 20) {
            return console.error('[tn-slide-verify]获取容器信息失败')
          }
          initCount++
          setTimeout(() => {
            _getSlideWrapperRectInfo()
          }, 50)
          return
        }

        initCount = 0
        res = res as UniApp.NodeInfo
        slideRect.width = res?.width || 0
        slideRect.height = res?.height || 0
      })
      .exec()
  }
  return {
    slideContainerRectID,
    slideRectID,
    slideWrapperRect,
    slideRect,
    distance,
    isPass,
    initRectInfo,
    slideStartTouchEvent,
    slideTouchMoveEvent,
    slideTouchEndEvent,
    resetSlideStatus
  }
}